package org.huangjiahui.rpc.factory;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.EqualsAndHashCode;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import java.util.Map;
import java.util.concurrent.*;



/**
 * @author huangjiahui
 *
 * 创建ThreadPool（线程池）的工具类
 */
@EqualsAndHashCode
public class ThreadPoolFactory {
    /**
     * 线程池参数
     */
    private static final int CORE_POOL_SIZE =10;
    private static final int MAXIMUM_POOL_SIZE_SIZE =100;
    private static final int KEEP_ALIVE_TIME =1;
    private static final int BLOCKING_QUEUE_CAPACITY=100;

    private final static Logger logger = LoggerFactory.getLogger(ThreadPoolFactory.class);

    private static Map<String, ExecutorService> threadPollsMap = new ConcurrentHashMap<>();

    private ThreadPoolFactory(){}

    @org.jetbrains.annotations.NotNull
    public static ExecutorService createDefaultThreadPool(String threadNamePrefix) {
        return createDefaultThreadPoll(threadNamePrefix,false);
    }

    @org.jetbrains.annotations.NotNull
    public static ExecutorService createDefaultThreadPoll(String threadNamePrefix, Boolean daemon){
        ExecutorService pool = threadPollsMap.computeIfAbsent(threadNamePrefix,k->createThreadPoll(threadNamePrefix,daemon));
        if(pool.isShutdown()|| pool.isTerminated()){
            threadPollsMap.remove(threadNamePrefix);
            pool = createThreadPoll(threadNamePrefix,daemon);
            threadPollsMap.put(threadNamePrefix,pool);
        }
        return pool;
    }

    public static void shutDownAll(){
        logger.info("关闭所有线程池");
        threadPollsMap.entrySet().parallelStream().forEach(entry -> {
            ExecutorService executorService = entry.getValue();
            executorService.shutdown();
            logger.info("关闭线程池[{}][{}]", entry.getKey(), executorService.isTerminated());
            try {
                executorService.awaitTermination(10, TimeUnit.SECONDS);
            }catch (InterruptedException ie){
                logger.error("关闭线程池失败");
                executorService.shutdownNow();
            }
        } );
    }

    private static ExecutorService createThreadPoll(String threadNamePrefix,Boolean daemon){
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(BLOCKING_QUEUE_CAPACITY);
        ThreadFactory threadFactory = createThreadFactory(threadNamePrefix,daemon);
        return new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE_SIZE, KEEP_ALIVE_TIME, TimeUnit.MINUTES, workQueue, threadFactory);
    }

    /**
     *  创建ThreadFactory，如果threadNamePrefix不为空返回guava的ThreadFactory，否则使用concurrent的faultThreadFactory
     * @param threadNamePrefix
     * @param daemon
     * @return ThreadFactory
     */
    private static ThreadFactory createThreadFactory(String threadNamePrefix,Boolean daemon){
        if(threadNamePrefix != null){
            if(daemon != null){
                return new ThreadFactoryBuilder().setNameFormat(threadNamePrefix + "-%d").setDaemon(daemon).build();
            }else{
                return new ThreadFactoryBuilder().setNameFormat(threadNamePrefix+"-%d").build();
            }
        }
        return Executors.defaultThreadFactory();
    }
}
